package nancal.mp.service

import io.kubernetes.client.openapi.ApiException
import io.kubernetes.client.openapi.apis.CoreV1Api
import io.kubernetes.client.openapi.models.V1ConfigMap
import io.kubernetes.client.openapi.models.V1ObjectMeta
import nbcp.base.comm.ApiResult
import nbcp.base.comm.JsonResult
import nbcp.base.comm.StringMap
import nbcp.base.comm.config
import nbcp.base.extend.AsString
import nbcp.base.extend.HasValue
import org.slf4j.LoggerFactory
import org.springframework.stereotype.Service

@Service
class K8sConfigMapService : K8sBaseService() {
    companion object {
        private val logger = LoggerFactory.getLogger(this::class.java.declaringClass)
    }


    /**
     * name = mp-gateway
     * items = application.yml to ... , application-dev.yml to ...
     */
//    data class ConfigMapDataItem(var name: String = "", var items: StringMap = StringMap())

    fun get(targetEnv: String, namespace: String, name: String): ApiResult<Map<String, String>> {
        var appApi = CoreV1Api(getK8sClient(targetEnv));

        var ret = appApi.listNamespacedConfigMap(
            namespace.AsString("default")
        ).execute()
            .items;

        if (name.HasValue) {
            ret = ret.filter { it.metadata.name == name }
        }

        if (ret.any() == false) {
            return ApiResult()
        }

        ret.first()
            .data
            .apply {
                return ApiResult.of(this)
            }
    }


    fun getItems(targetEnv: String, namespace: String, name: String): ApiResult<StringMap> {
        var appApi = CoreV1Api(getK8sClient(targetEnv));

        try {
            appApi.readNamespacedConfigMap(
                name,
                namespace.AsString("default"),
            )
                .execute()
                .data
                .apply {
                    return ApiResult.of(StringMap(this ?: mapOf()))
                }
        } catch (e: ApiException) {
            if (e.code == 404) {
                return ApiResult.of(StringMap())
            }
        } catch (e: Exception) {
            return ApiResult.of(StringMap())
        }

        return ApiResult.of(StringMap())
    }


    fun setContent(
        targetEnv: String,
        namespace: String,
        name: String,
        itemName: String,
        itemContent: String
    ): JsonResult {
        var appApi = CoreV1Api(getK8sClient(targetEnv));

        var oriData: V1ConfigMap? = null;
        try {
            oriData = appApi.readNamespacedConfigMap(
                name,
                namespace.AsString("default"),
            ).execute()

        } catch (e: ApiException) {
            if (e.code == 404) {
                oriData = V1ConfigMap()
                oriData.apiVersion = "v1"
                oriData.kind = "ConfigMap"

                oriData.data = mutableMapOf()

                var meta = V1ObjectMeta();
                meta.name = name;
                meta.namespace = namespace

                oriData.metadata = meta

                var nc =
                    appApi.createNamespacedConfigMap(namespace.AsString("default"), oriData)
                        .execute()

                if (nc == null) {
                    return JsonResult.error("创建失败")
                }

                oriData = appApi.readNamespacedConfigMap(
                    name,
                    namespace.AsString("default"),
                ).execute()
            } else {
                throw RuntimeException(e.message, e);
            }
        }

        if (oriData == null) {
            throw RuntimeException("找不到 configmap 数据！")
        }

        oriData.putDataItem(itemName, itemContent)

        var v1ConfigMap = appApi.replaceNamespacedConfigMap(
            name,
            namespace.AsString("default"),
            oriData
        ).execute()

        if (v1ConfigMap == null) {
            return JsonResult.error("创建失败")
        }

        return JsonResult()
    }


    /**
     * 设置 ngin configmap web.conf
     */
    fun setNginxConfWebConf(targetEnv: String, namespace: String, path: String, serviceName: String): Boolean {
        var location = path.replace(".", "").replace("/", "").trim();

        if (location.isEmpty()) {
            return false;
        }

        if (!location.startsWith("/")) {
            location = "/" + location
        }

        var k8s_ns = namespace.AsString(config.appGroup.AsString("default"));


        var k8s_items = getItems(targetEnv, k8s_ns, "nginxconf").run {
            if (this.msg.HasValue) {
                throw java.lang.RuntimeException(this.msg)
            }
            return@run this.data ?: StringMap()
        }

        var oriContent = k8s_items.get("${serviceName}.web-conf").AsString();

        var newContent = """
# 由发版工具生成
location ${location} {
    proxy_pass http://${serviceName};
    proxy_redirect off;
    proxy_set_header Host  ${'$'}host;
    proxy_set_header X-Real-IP ${'$'}remote_addr;
    proxy_set_header X-Forwarded-For ${'$'}proxy_add_x_forwarded_for;
}
"""
        if (oriContent.trim() != newContent.trim()) {
            setContent(
                targetEnv,
                k8s_ns,
                "nginxconf",
                "${serviceName}.web-conf",
                newContent
            );

            //要重启nginx
            return true;
        }
        return false;
    }
}